package cn.summit.config;

import cn.summit.service.impl.MySuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.WebAuthenticationDetails;

import java.util.ArrayList;
import java.util.List;

/**
 * 配置spring security
 *
 * @author summit
 * @since 2020/2/6 16:18
 */
@Configuration
//@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 密码编码器
     *
     * @return 编码器
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    public static void main(String[] args) {
        System.out.println(new BCryptPasswordEncoder().encode("123456"));
    }

    //    /**
    //     * 定义用户信息
    //     *
    //     * @return 结果
    //     */
    //    @Override
    //    @Bean
    //    protected UserDetailsService userDetailsService() {
    //        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
    //        manager.createUser(User.withUsername("summit").password(passwordEncoder().encode("123456")).authorities("t1").build());
    //        manager.createUser(User.withUsername("lisi").password(passwordEncoder().encode("123")).authorities("t2").build());
    //        return manager;
    //    }

    //    /**
    //     * @param auth
    //     * @throws Exception
    //     */
    //    @Override
    //    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    //        auth.inMemoryAuthentication()
    //              //  .passwordEncoder(passwordEncoder())
    //                .withUser("summit")
    //                .password(passwordEncoder().encode("123456"))
    //                .authorities("PRODUCT_ADD");
    //    }

    @Override
    public void configure(AuthenticationManagerBuilder auth){
        auth.authenticationProvider(authenticationProvider());
    }
    @Bean
    public AuthenticationProvider authenticationProvider() {
        return new AuthenticationProvider() {
            //检查入参Authentication是否是UsernamePasswordAuthenticationToken或它的子类
            @Override
            public boolean supports(Class<?> authentication) {
                return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
            }

            @Override
            public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                //第4篇讲过的其他参数，默认details类型中包含用户ip和sessionId
                WebAuthenticationDetails details = (WebAuthenticationDetails) authentication.getDetails();
                //用户名和密码
                String username = authentication.getName();
                String password = authentication.getCredentials().toString();
                //根据以上参数，自定义认证逻辑，系统默认实现就是在此读取UserDetails认证密码
                //这里只给个简化逻辑，验证密码是否是123，实际中要根据具体业务来实现
                if (!password.equals("123")) {
                    throw new BadCredentialsException("密码错误");
                }
                // 认证通过，从数据库中查询用户权限
                List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
                authorities.add(new SimpleGrantedAuthority("ROLE_role1"));
                //生成已认证Authentication，系统会将其写入SecurityContext
                return new UsernamePasswordAuthenticationToken(username, password, authorities);
            }
        };
    }

    @Autowired
    private MySuccessHandler mySuccessHandler;
    /**
     * 安全拦截
     *
     * @param http 安全控制
     * @throws Exception 异常
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
            //拥有t1权限才能访问
            //                .antMatchers("/t1/**").hasAuthority("t1")
            //                .antMatchers("/t2/**").hasAuthority("t2")
            .antMatchers("/loginpage").permitAll().antMatchers("/**")
            .authenticated()//所有/**的请求必须认证通过
            .anyRequest().permitAll()//除了/**，其它的请求可以访问
            .and()
            // .httpBasic() //弹窗
            .formLogin()//允许表单登入
            .loginPage("/loginpage")//登录页面
            .loginProcessingUrl("/login2")
            //.successHandler(mySuccessHandler)
        //  .successForwardUrl("/test")//自定义登录成功的页面地址

        ;
    }


    @Override
    public void configure(WebSecurity web) throws Exception {
        // 登录页面请求不走 Spring Security 过滤器链
        web.ignoring().mvcMatchers("/login.html");
    }

    // @Autowired
    // private CustmService custmService;
    // /**
    //  * successForwardUrl只支持post,然后就重定向到指定登入成功后的页面
    //  *
    //  * @return 登入成功后处理
    //  */
    // private AuthenticationSuccessHandler getSuccessHandler() {
    //     AuthenticationSuccessHandler handler = (httpServletRequest, httpServletResponse, authentication) -> {
    //         int test = custmService.getTest();
    //         String url;
    //         if (test == 0) {
    //             url = "/index";
    //         } else {
    //             url = "/t1/add";
    //         }
    //         httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + url);
    //     };
    //     return handler;
    // }
    //

}
